﻿using System;
using System.Linq;
using System.Diagnostics;
using Optum.SN.Infra.Core.Model.Repository;
using Optum.SN.Infra.Core.Dependency.Service;

namespace Optum.SN.Infra.Core.TestBase
{
    /// <summary>
    /// Common API for database integration tests.
    /// </summary>
    public abstract class DbTestBase
    {
        /// <summary>
        /// Creates concrete repository and sets database context and logging delegate.
        /// </summary>
        /// <typeparam name="T">Repository record type.</typeparam>
        /// <param name="dbContext">Database context for the repository.</param>
        /// <returns>Typed repository.</returns>
        protected virtual IRepository<T> GetRepository<T>(IDbContext dbContext) where T : class, IEntity
        {
            return new Repository<T> {DbContext = dbContext, Log = Log};
        }
        /// <summary>
        /// Creates concrete repository for asynchronous data access and sets database context and logging delegate.
        /// </summary>
        /// <typeparam name="T">Repository record type.</typeparam>
        /// <param name="dbContext">Database context for the repository.</param>
        /// <returns>Typed repository.</returns>
        protected virtual IRepositoryAsync<T> GetRepositoryAsync<T>(IDbContext dbContext) where T : class, IEntity
        {
            return new RepositoryAsync<T> { DbContext = dbContext, Log = Log };
        }
        /// <summary>
        /// Logs specified data elements.
        /// </summary>
        /// <typeparam name="T">Source record type.</typeparam>
        /// <param name="source">Source records.</param>
        /// <param name="getFields">Delegates to fetch field values.</param>
        protected void LogData<T>(IQueryable<T> source, params Func<T, string>[] getFields)
        {
            foreach (T record in source)
                foreach (Func<T, string> field in getFields)
                    Log(field(record));
        }
        /// <summary>
        /// Logs information.
        /// </summary>
        /// <param name="data">Data element to log.</param>
        protected void Log(string data)
        {
            Trace.WriteLine(string.Format("[{0}]: {1}", DateTime.Now, data));
        }
    }
}